package com.zhny.iot.yw.pluginHz;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.aiot.plugin.mqtt.MqttDevice;
import com.zhny.iot.yw.pluginHz.config.YWFertilizerMqttConfig;
import com.zhny.iot.yw.pluginHz.model.FertilizerParam;
import com.zhny.iot.yw.pluginHz.model.YWFertilizerStoreEntity;
import io.netty.util.internal.StringUtil;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.pf4j.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.function.BiConsumer;

/**
 * @Author pengshuai
 * @Date 2025/3/7
 */

public class YWFertilizerMqttDevice extends MqttDevice<YWFertilizerMqttConfig> {

    private final Map<String, String> CommandOperations;

    public YWFertilizerMqttDevice(IDeviceFactory<YWFertilizerMqttConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super(factory, centerFacilities, entity);
        CommandOperations=new ImmutableMap.Builder<String, String>()
                .put("start","{\"r\": \"1.6\", \"v\": 1}")
                .put("stop","{\"r\": \"1.7\", \"v\": 0}")
                .put("setRunTimeValue","{\"r\": \"1.9\", \"v\": -1}")
                .put("readAll","{\"r\": \"1.0\", \"v\": 0}")
                .build();
    }

    @Override
    protected String[] getSubscribeTopics(){
        check();
        String sn = this.getConfig().getSn();
        return new String[]{
                "/"+sn+"/r"
        };
    }

    @Override
    protected BiConsumer<String, MqttMessage> getMessageCallback(){
        return (topic,msg)->{
            byte[] buf = msg.getPayload ();
            try {
                String payload = new String(buf,"utf-8");
                logger.info ("主题：{},内容:{}",topic,payload);
                if(StringUtils.isNotNullOrEmpty(payload)){
                    JSONObject bodyData = JSONObject.parse(payload);
                    YWFertilizerStoreEntity entry = new YWFertilizerStoreEntity();
                    if(bodyData.containsKey("v") && bodyData.get("v") != null){
                        JSONArray dataList = bodyData.getJSONArray("v");
                        for(int i=0;i<dataList.size();i++){
                            JSONObject data = dataList.getJSONObject(i);
                            if(data.containsKey("r")){
                                switch (data.get("r").toString()){
                                    case "1.1" :
                                    case "1.2" :
                                        entry.setOutValveStatus("1".equals(data.getString("v")) ? "开启" : "关闭");
                                        break;
                                    case "1.3" :
                                    case "1.4" :
                                        entry.setPumpRunStatus("1".equals(data.getString("v")) ? "正常" : "故障");
                                        break;
                                    case "1.5" :
                                        entry.setOperateModelStatus("1".equals(data.getString("v")) ? "远程" : "就地");
                                        break;
                                    case "1.6" :
                                    case "1.7" :
                                        entry.setPumpStatus("1".equals(data.getString("v")) ? "启动" : "停止");
                                        break;
                                    case "1.8" :
                                        entry.setRunTime(data.getString("v"));
                                        break;
                                    case "1.9" :
                                        entry.setRunTimeSetValue(data.getString("v"));
                                        break;
                                    default: break;
                                }
                            }
                        }
                    }

                    saveReal(entry);
                    save(entry);

                    MessageEntry msgEntry = MessageUtils.createMessageEntry(this.getId());
                    msgEntry.setType(MessageType.RESULT);
                    msgEntry.setData(entry);
                    nofity(msgEntry);
                }
            } catch (UnsupportedEncodingException e) {
                logger.error ("消息解码失败！",e);
            }
        };
    }

    @Override
    public MessageEntry onReceiveTask(TaskEntity entity){
        logger.info("水肥控制指令任务：方法：{}，参数：{}",entity.getMethodName(),entity.getParams());
        MessageEntry msgEntry = super.onReceiveTask(entity);
        String method = entity.getMethodName();
        if(StringUtils.isNullOrEmpty(method)){
            msgEntry.setType(MessageType.ERROR);
            msgEntry.setData("水肥机动作是空的");
            return msgEntry;
        }
        if(!CommandOperations.containsKey(method)){
            msgEntry.setType(MessageType.ERROR);
            msgEntry.setData ("水肥机动作不存在");
            return msgEntry;
        }
        if("readAll".equals(method)){//该设备主动上报 不支持主动问询
            return null;
        }
        String body = CommandOperations.get(method);
        JSONObject jsonBody = new JSONObject();
        JSONArray commands = new JSONArray();
        JSONObject command = JSONObject.parse(body);
        if((int)command.get("v") < 0){
            FertilizerParam param = null;
            String taskParam = entity.getParams();
            ObjectMapper mapper = new ObjectMapper();
            try{
                param = mapper.readValue(taskParam,FertilizerParam.class);
                String value = param.getValue();
                if(value.contains(".")){
                    command.put("v",Double.parseDouble(param.getValue()));
                }else{
                    command.put("v",Integer.parseInt(param.getValue()));
                }
            }catch (Exception e){
                logger.error ("Parse param error !");
                return  null;
            }
        }
        commands.add(command);
        jsonBody.put("t","w");
        jsonBody.put("v",commands);
        String sn = this.getConfig().getSn();
        try {
            logger.info("水肥机{}数据推送：{}",this.getDeviceEntity().getName(),jsonBody.toJSONString());
            //下发格式
            //{
            //    "t":"w",
            //    "v":[{"r":"1.8","v":0}]
            //}
            pushMessage("/"+sn+"/w",jsonBody.toJSONString());
        }catch (Exception e){
            logger.info ("水肥机MQTT数据推送失败！",e);
            msgEntry.setType (MessageType.ERROR);
            msgEntry.setData("水肥机MQTT数据推送失败");
            return msgEntry;
        }
        nofity (msgEntry);
        return msgEntry;
    }

    private void check(){
        YWFertilizerMqttConfig config = this.getConfig ();
        if(config == null)
            throw new NullPointerException("水肥机配置必填！");
        String sn = config.getSn();
        String host = config.getHost();
        String userName = config.getUserName();
        String passWord = config.getPassWord();
        String clientId = config.getClientId();
        if(StringUtils.isNullOrEmpty(sn))
            throw new NullPointerException("水肥机设备序列号必填");
        if(StringUtils.isNullOrEmpty(host))
            throw new NullPointerException("水肥机mqtt地址必填");
        if(StringUtils.isNullOrEmpty(userName))
            throw new NullPointerException("水肥机mqtt账号必填");
        if(StringUtils.isNullOrEmpty(passWord))
            throw new NullPointerException("水肥机mqtt密码必填");
        if(StringUtils.isNullOrEmpty(clientId))
            throw new NullPointerException("水肥机mqtt客户端连接号必填");
    }

    private <T> T mapTo(String body, TypeReference<T> valueTypeRef){
        if(StringUtil.isNullOrEmpty (body))
            return null;
        ObjectMapper mapper=new ObjectMapper ();
        try {
            mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
            return mapper.readValue(body,valueTypeRef);
        } catch (IOException e) {
            return null;
        }
    }
}
